package com.panda.utils;


import com.panda.git.PullUtils;
import com.panda.pojo.Context;
import com.panda.pojo.Document;
import com.panda.pojo.Scope;
import com.panda.pojo.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//解析服务的引用
class ServiceUtils {

    private static final Pattern dep = Pattern.compile("(?<=^|[\n;{]) *dep[\n| ]+(@?[a-zA-Z][a-zA-Z0-9./]*( +as +[a-zA-Z][a-zA-Z0-9]*)?([\n| ]*,[\n| ]*@?[a-zA-Z][a-zA-Z0-9./]*( +as +[a-zA-Z][a-zA-Z0-9]*)?)*) *(?=[\n;}]|$)");

    //处理引用
    static String transformDep(Context context, Scope scope, String s) {

        if ("".equals(s)) {
            return s;
        }

        Matcher matcher = dep.matcher(s);

        Set<String> svs = new HashSet<>();

        while (matcher.find()) {

            String[] split = matcher.group(1).split(",");

            String ta = "";

            String js_hide = IdUtils.create("__js_hide");

            s = s.replace(matcher.group(), js_hide + "\n\n");

            for (String sa : split) {

                String[] strings = sa.split("as");

                String sv = strings[0];

                if (sv.contains("/")) {

                    if (sv.startsWith("@")) {


                        String[] sp = sv.substring(1).split("/");


                        if (sp.length > 3) {

                            String group = sp[0];
                            String root = sp[1];
                            String version = sp[2];


                            //拉取
                            if (!PullUtils.pull(context, group, root, version, null)) {
                                throw new RuntimeException("服务不存在或已失效: " + sv);
                            }

                            //替换名称
                            sv = sv.replace("@", "__");

                        } else {
                            throw new RuntimeException("无效的服务依赖: " + sv);
                        }

                    }


                    String t = sv.replace("/", "_").replace(".", "_").trim();

                    scope.addDependence(t);

                    String r = sv.substring(sv.lastIndexOf("/") + 1);

                    if (svs.contains(r)) {
                        throw new RuntimeException("存在同名服务,使用as关键字进行区分: " + r);
                    }

                    svs.add(r);

                    if (strings.length == 2) {
                        ta += "\nvar " + strings[1] + "=" + t + "\n";
                    }

                    s = s.replaceAll("(?<=[^a-zA-Z0-9_]|^)" + r + "(?=[^a-zA-Z0-9_]|$)", t);

                } else {

                    if (svs.contains(sv)) {
                        throw new RuntimeException("存在同名服务,使用as关键字进行区分: " + sv);
                    }

                    svs.add(sv);

                    if (strings.length == 2) {
                        ta += "\nvar " + strings[1] + "=" + sv + "\n";
                    }

                    scope.addDependence(sv.trim());
                }


            }

            s = s.replace(js_hide, ta);

        }

        return s;

    }


    //从一个服务文档中分隔出多个服务的字符串
    private static Map<String, Service> splitService(Context context, String s) {

        List<Document> documents = DocumentSlicer.splice(s);

        Map<String, Service> map = new HashMap<>();

        documents.forEach(document -> {

            Service service = new Service();

            String body = document.getBody();

            Set<String> deps = document.getDeps();

            if (deps != null) {

                Set<String> stringSet = new HashSet<>();
                for (String dep : deps) {

                    if (dep.contains("/")) {


                        if (dep.startsWith("@")) {


                            String[] sp = dep.substring(1).split("/");


                            if (sp.length > 3) {

                                String group = sp[0];
                                String root = sp[1];
                                String version = sp[2];


                                //拉取
                                if (!PullUtils.pull(context, group, root, version, null)) {
                                    throw new RuntimeException("服务不存在或已失效: " + dep);
                                }

                                //替换名称
                                dep = dep.replace("@", "__");

                            } else {
                                throw new RuntimeException("无效的服务依赖: " + dep);
                            }

                        }

                        String r = dep.replace("/", "_");

                        stringSet.add(r);

                        String sv = dep.substring(dep.lastIndexOf('/') + 1);

                        //服务名称替换
                        body = body.replace(sv, r);

                    } else {
                        stringSet.add(dep);
                    }

                }

                service.setDependencies(stringSet);

            }

            service.setBody(body);

            Document.Files files = document.getFiles();

            if (files != null) {

                service.setCss(files.getCss());
                service.setJs(files.getJs());

            }

            String namespace = document.getNamespace();

            if (namespace == null) {
                service.setName(document.getName());
                Service old = map.put(service.getName(), service);

                if (old != null) {
                    throw new RuntimeException("已存在相同服务:" + service.getName() + " 请考虑使用不同名称的服务,或使用命名空间区分");
                }

            } else {

                String name = namespace + "/" + document.getName();

                service.setName(name.replace("/", "_"));

                //依赖
                Service old = map.put(service.getName(), service);

                if (old != null) {
                    throw new RuntimeException("已存在相同服务:" + name + " 请考虑使用不同名称的服务,或使用其他命名空间区分");
                }
            }


        });


        return map;

    }



    static void handle(Context context, List<String> serviceTexts) {


        if (serviceTexts.size() > 0) {

            Map<String, Service> serviceMap = new HashMap<>();

            serviceTexts.forEach(s -> {


                Map<String, String> map = new HashMap<>();

                //提取字符串
                s = StringUtils.extract(map, s);

                s = StringUtils.removeAnnotation(s);

                Map<String, Service> rs = splitService(context, s);

                Set<String> set = rs.keySet();

                //字符串回填
                for (String key : set) {
                    Service service = rs.get(key);
                    service.setBody(StringUtils.fillBack(map, service.getBody()));
                }

                if (rs.size() > 0) {
                    serviceMap.putAll(rs);
                }


            });

            context.setServiceMap(serviceMap);

        }

    }

    /*

        从文本中快速定义服务

        可以写成标签的形式


     */


}
